home *** CD-ROM | disk | FTP | other *** search
- /*
- * LightspeedC source for PDEF 0, routines to implement draft mode printing
- * on a serial device.
- * Earle R. Horton, September 19, 1987.
- * All rights reserved.
- */
-
- #include "prglobals.h"
- #include <EventMgr.h>
-
- pascal TPPrPort myPrOpenDoc();
- pascal void myPrCloseDoc();
- pascal void myPrOpenPage();
- pascal void myPrClosePage();
- pascal void myStdText();
- pascal int myStdTextMeas();
- void myClearPage();
- Ptr allocate();
- void free();
- void bcopy();
- DPstorage DrvrStorage();
- void checkabort();
-
- main(){
- asm{
- dc.w ILLEGAL ;; So I can find it...
- jmp myPrOpenDoc
- jmp myPrCloseDoc
- jmp myPrOpenPage
- jmp myPrClosePage
-
- }
- }
- /*
- * This function is supposed to return a pointer to a specialized GrafPort
- * (a TPrPort) customized for printing. Due to the paucity of documentation
- * on how to go about this, I do not know whether I am going about this in
- * exactly the right way, but I sure hope so. I set portBits.bounds for the
- * port to the empty Rect {0,0,0,0} and then install the standard QuickDraw
- * routines as GrafProcs. In place of StdText, I put my own StdText routine.
- * Hopefully, QuickDraw will keep track of the correct pen location for me,
- * and call my routine whenever it is necessary to draw text. I just put
- * the text in a big buffer for now, and then print it out when I get called
- * to close the current page. This takes up some memory, but solves the
- * problem of what to do when the application wants a reverse line feed.
- * Other tasks:
- * save a copy of the user print record for later use in formatting the
- * output page
- * save a copy of the user print record in the printer resource file
- */
- pascal TPPrPort myPrOpenDoc(hPrint,pPrPort,pIOBuf)
- THPrint hPrint;
- TPPrPort pPrPort;
- Ptr pIOBuf;
- {
- TPPrPort thisport;
- pline thepage;
- Handle us;
- register DPstorage dsp;
- THPrint savePrint;
- PrParam *pb;
-
- us = (Handle)(GetResource('PDEF',0));
- asm{
- move.l us,a0
- HLock
- }
- /* Assign storage for printing port and page buffer. */
- if((thepage = (pline)allocate((long)(NROWS*sizeof(line)))) == nil){
- PrintErr = iMemFullErr;
- return nil;
- }
- else if(pPrPort == nil){
- if((thisport = (TPPrPort)
- allocate((long)sizeof(TPrPort))) == nil){
- free(thepage);
- PrintErr = iMemFullErr;
- return(nil);
- }
- thisport->fOurPtr = TRUE;
- }
- else {
- thisport = pPrPort;
- thisport->fOurPtr = FALSE;
- }
- /* Copy print record into private storage area. */
- dsp = DrvrStorage();
- pb = &dsp->prpb;
- dsp->Print = **hPrint;
- thisport->lGParam4 = (long)thepage;
- dsp->Print.prJob.bJDocLoop = bDraftLoop;
- OpenPort(thisport);
- /* Fill out gProcs for this port. */
- SetStdProcs(&thisport->gProcs);
- thisport->gProcs.textProc = (QDPtr)myStdText;
- thisport->gProcs.txMeasProc = (QDPtr)myStdTextMeas;
-
- thisport->gPort.grafProcs = &thisport->gProcs;
- /*
- * Set up the port Rect in the proper coordinates, relative to the page
- * and to the paper.
- */
- thisport->gPort.device = dsp->Print.prInfo.iDev;
- thisport->gPort.portRect = dsp->Print.prInfo.rPage;
- thisport->gPort.portBits.bounds.top =
- thisport->gPort.portBits.bounds.left =
- thisport->gPort.portBits.bounds.bottom =
- thisport->gPort.portBits.bounds.right = 0;
-
-
- SetPort(thisport);
- /* Offset the page (portRect) relative to the paper. */
- PortSize
- (dsp->Print.prInfo.rPage.right,dsp->Print.prInfo.rPage.bottom);
- MovePortTo(- dsp->Print.rPaper.left, - dsp->Print.rPaper.top);
- GrafDevice(dsp->Print.prInfo.iDev);
- myClearPage(thepage);
- pb->csCode = iPrDevCtl; /* Init the printer. */
- pb->lParam1 = lPrReset; /* Driver code does the work. */
- asm{
- move.l pb,a0
- PBControl
- }
- dsp->pagenum = 1;
- if(dsp->Print.prJob.pIdleProc == nil)
- dsp->Print.prJob.pIdleProc = (ProcPtr)checkabort;
- savePrint = (THPrint)GetResource('PREC',1);
- if(savePrint != nil){
- LoadResource(savePrint);
- **savePrint = dsp->Print;
- ChangedResource(savePrint);
- ReleaseResource(savePrint);
- } /* Determine proper margins. */
- dsp->nlines = (dsp->Print.rPaper.bottom - dsp->Print.rPaper.top)/
- CHARHEIGHT;
- return(thisport);
- }
- pascal void myPrCloseDoc(pPrPort)
- TPPrPort pPrPort;
- {
- pline thepage;
- Pfg settings;
-
- free(pPrPort->lGParam4);
- ClosePort(pPrPort);
- if(pPrPort->fOurPtr) free(pPrPort);
- }
- /*
- * This routine opens a new page. Actually, all it does is clear out the
- * array of lines in preparation for more fun with QuickDraw. I suppose it
- * could also send a reset command to the driver...
- */
- pascal void myPrOpenPage(pPrPort,pPageFrame)
- TPPrPort pPrPort;
- TPRect pPageFrame;
- {
- register DPstorage dsp;
- dsp = DrvrStorage();
- if(pPageFrame != nil)
- *pPageFrame = dsp->Print.prInfo.rPage;
- SetPort(pPrPort);
-
- myClearPage(pPrPort->lGParam4);
- }
- /*
- * This is the routine which does the actual printing. QuickDraw calls
- * which have called our StdText substitute routine have filled up a
- * buffer with lines of text. Now, we just get the buffer and print it.
- */
- pascal void myPrClosePage(pPrPort)
- TPPrPort pPrPort;
- {
- register DPstorage dsp;
- register pline theline;
- register int i,iocount;
- PrParam *pb;
-
- dsp = DrvrStorage();
- pb = &dsp->prpb;
- if(dsp->pagenum < dsp->Print.prJob.iFstPage){
- dsp->pagenum++;
- return;
- }
- if(dsp->pagenum++ > dsp->Print.prJob.iLstPage){
- PrintErr = iPrAbort;
- if (dsp->preofstr[0] != '\0'){
- pb->csCode = iPrIOCtl;
- pb->lParam1 = (long)(&dsp->preofstr[1]);
- pb->lParam2 = (long)dsp->preofstr[0];
- asm{
- move.l pb,a0
- PBControl
- }
- }
- return;
- }
- if(dsp->Print.prStl.feed != feedCut || waitnextpage()){
- theline = (pline)pPrPort->lGParam4;
- if (dsp->prtopstr[0] != '\0'){
- pb->csCode = iPrIOCtl;
- pb->lParam1 = (long)(&dsp->prtopstr[1]);
- pb->lParam2 = (long)dsp->prtopstr[0];
- asm{
- move.l pb,a0
- PBControl
- }
- }
- for(i=0;dsp->nlines - i;i++){
- (* dsp->Print.prJob.pIdleProc)();
- if(PrintErr == iPrAbort)return;
- if((theline+i)->dirty == DIRTY){
- iocount = WIDTH;
- while( (theline+i)->text[--iocount] == ' '){}
- ++iocount;
- pb->csCode = iPrIOCtl;
- pb->lParam1 =
- (long)(&(theline+i)->text[0]);
- pb->lParam2 = (long)iocount;
- asm{
- move.l pb,a0
- PBControl
- }
- }
- pb->csCode = iPrDevCtl;
- if(i < dsp->nlines - 1)
- pb->lParam1 = lPrLineFeed;
- else pb->lParam1 = lPrPageEnd;
- asm{
- move.l pb,a0
- PBControl
- }
- }
- }
- else PrintErr = iPrAbort;
- }
- /*
- * All text drawing calls in the TPrPort get sent here. Find the current
- * pen location and translate it to row and column of the page buffer,
- * squirt the text into the buffer.
- */
- pascal void myStdText(byteCount,textBuf,numer,denom)
- int byteCount;
- QDPtr textBuf;
- Point numer,denom;
- {
- Point thepoint;
- TPPrPort tp;
- pline thepage;
- int width;
- int x,y;
- GetPort(&tp);
- if(tp->gPort.device == IDEV10) width = 7;
- else if(tp->gPort.device == IDEV15) width = 5;
- else width = 6;
- thepage = (pline)tp->lGParam4;
- GetPen(&thepoint);
- /* (Local is page, Global is paper.) */
- LocalToGlobal(&thepoint);
- x = thepoint.h/width;
- y = thepoint.v/CHARHEIGHT;
- bcopy(textBuf,&((thepage+y)->text[x]),byteCount);
- (thepage+y)->dirty = DIRTY;
- Move(width*byteCount,0);
- }
- pascal int myStdTextMeas(byteCount,textBuf,numer,denom,info)
- int byteCount;
- QDPtr textBuf;
- Point *numer,*denom;
- FontInfo *info;
- {
- TPPrPort tp;
- GetPort(&tp);
- if(tp->gPort.device == IDEV10)info->widMax = 7;
- else if(tp->gPort.device == IDEV15)info->widMax = 5;
- else info->widMax = 6;
- info->ascent = 9;
- info->descent = 2;
- info->leading = 0;
- numer->v = denom->v = 1;
- denom->h = 6;
- numer->h = info->widMax;
- return (info->widMax * byteCount);
- }
- void myClearPage(theline)
- pline theline;
- {
- int count;
- unsigned char *ch;
-
- count = NROWS;
- clear:
- theline->dirty = ~DIRTY;
- ch = &theline->text[0];
- asm{
- move.l ch,a0
- move.w #((WIDTH/4)-1),d0
- move.l #0x20202020,d1
- loop:
- move.l d1,(a0)+
- dbra d0,@loop
- }
- if(--count){
- theline++;
- goto clear;
- }
- }
- Ptr allocate(size)
- long size;
- {
- asm{
- move.l size,d0
- NewPtr
- move.l a0,d0 ;; LightspeedC returns function
- } /* value in d0. */
- }
- void free(ptr)
- Ptr ptr;
- {
- asm{
- move.l ptr,a0
- DisposPtr
- }
- }
- /*
- * A UNIXism. Want to make something of it?
- */
- void bcopy(src,dst,count)
- unsigned char *src,*dst;
- int count;
- {
- asm{
- move.l src,a0
- move.l dst,a1
- clr.l d0
- move.w count,d0
- BlockMove
- }
- }
- #define UTableBase 284
- /*
- * This function returns a pointer to the printer driver's private
- * storage. We don't need to lock the Handle, since it is always locked
- * when the driver is open.
- */
- DPstorage DrvrStorage()
- {
- DCtlHandle ourDCtlEntry;
- DHstorage ourdCtlStorage;
- asm{
- move #2,d0
- asl.l #2,d0 ;; d0 = 8L
- move.l UTableBase,a0 ;; a0 -> base of unit table
- adda d0,a0 ;; a0 -> second entry
- move.l (a0),ourDCtlEntry ;; handle to DCtlEntry[2]
- }
- ourdCtlStorage = (DHstorage)(*ourDCtlEntry)->dCtlStorage;
- return(*ourdCtlStorage);
- }
- /*
- * Abort printing if command '.' pressed.
- */
- void checkabort()
- {
- EventRecord myevent;
- int c;
- if (GetNextEvent(keyDownMask, &myevent)){
- if(LoWord(myevent.message & charCodeMask) == '.' &&
- (myevent.modifiers & cmdKey) ){
- PrintErr = iPrAbort;
- }
- }
- }
- /*
- * Modal dialog box: "Insert next sheet."
- */
- waitnextpage()
- {
- DialogPtr sheetdialog;
- WindowPtr tempport;
- int itemhit,donetype;
- Handle doneitem;
- Rect donebox;
- if((sheetdialog = GetNewDialog(SHEETDIALOG, 0L,(WindowPtr) -1)) == nil)
- return FALSE;
- InitCursor();
- GetDItem(sheetdialog,DONEITEM,&donetype,&doneitem,&donebox);
- GetPort(&tempport);
- SetPort(sheetdialog);
- PenSize(3,3);
- InsetRect(&donebox,-4,-4);
- FrameRoundRect(&donebox,16,16);
- ModalDialog(0L,&itemhit);
- DisposDialog(sheetdialog);
- SetPort(tempport);
- if(itemhit == STOPITEM) return FALSE;
- return TRUE;
- }
-